import type { RoutePath } from '@/types/route-path'
import { orderApi } from '@/request/api'
import { useAppConfig, useDevice } from '@/stores'
import { to } from 'await-to-js'
import dayjs from 'dayjs'
import duration from 'dayjs/plugin/duration.js'
import { isEmpty, isNil, isPlainObject, omit, pick } from 'lodash-es'

dayjs.extend(duration)

/** 开发打印 */
export const useConsole = INDEV ? console : null

/** 延迟 */
export function useDelay(t?: number) {
  return new Promise(r => setTimeout(r, t))
}

/** 设计稿像素转小程序像素(含Dpr) */
export function usePx(px: number, withDpr?: boolean) {
  if (withDpr) {
    return uni.upx2px(px) * useDevice().windowInfo.pixelRatio
  }
  return uni.upx2px(px)
}

type RouteQuery = Record<string, string | number | boolean | undefined>
/** json转化成url参数格式 */
export function jsonToQueryString(json: RouteQuery) {
  const array: string[] = []
  for (const key in json) {
    if (!isNil(json[key]) && Object.prototype.hasOwnProperty.call(json, key)) {
      // const k = encodeURIComponent(key)
      const v = encodeURIComponent(json[key])
      array.push(`${key}=${v ?? ''}`)
      // array.push(`${key}=${json[key]}`)
    }
  }
  return array.join('&')
}

/** 简单路由 SwitchTab (tabBar 页) */
export async function useSwitchTab(path: RoutePath, options?: Partial<Omit<UniApp.SwitchTabOptions, 'url'>>) {
  uni.switchTab({
    url: `/pages${path}`,
    ...options,
  })
}

type NavOptions = { root?: string, replace?: boolean } & Partial<Omit<UniApp.NavigateToOptions, 'url'>>
/** 简单路由 navigate/redirect (非 tabBar 页) */
export async function useNav(path: RoutePath, query?: RouteQuery, options?: NavOptions) {
  let url = `${options?.root ?? '/pages'}${path}`

  if (!isEmpty(query) && isPlainObject(query)) {
    url += `?${jsonToQueryString(query)}`
  }
  if (options?.replace) {
    uni.redirectTo({ url, ...omit(options, ['query', 'replace']) })
  }
  else {
    uni.navigateTo({ url, ...omit(options, ['query', 'replace']) })
  }
}

type ReLaunchOptions = { root: string } & Partial<Omit<UniApp.ReLaunchOptions, 'url'>>
/** 简单路由 Relaunch (任意页) */
export async function useRelaunch(path: RoutePath, query?: RouteQuery, options?: ReLaunchOptions) {
  let url = `${options?.root ?? '/pages'}${path}`

  if (!isEmpty(query) && isPlainObject(query)) {
    url += `?${jsonToQueryString(query)}`
  }
  uni.reLaunch({
    url,
    ...options,
  })
}

/** 返回 如果路由只有一个则跳转首页 */
export function useNavBack(options?: UniApp.NavigateBackOptions, path?: RoutePath) {
  const pages = getCurrentPages()
  if (pages.length === 1) {
    useRelaunch('/home/index')
  }
  else if (!isNil(path)) {
    useRelaunch(path)
  }
  else {
    uni.navigateBack(options)
  }
}

/** 当前页路由信息 */
export function useCurrentPage() {
  const pages = getCurrentPages<{
    options: Record<string, any>
    $page?: Record<string, any>
  }>()
  const page = pages[pages.length - 1]
  return {
    route: page.route as string,
    query: page.options,
    fullPath: !isNil(page.$page) ? page.$page.fullPath : `${page.route}?${jsonToQueryString(page.options)}`,
  }
}

/** 弹窗，默认带主题色按钮 */
export function useModal(options: Omit<UniApp.ShowModalOptions, 'success' | 'fail' | 'complete'>) {
  return uni.showModal({
    // #ifndef MP-ALIPAY
    confirmColor: '#f7920d',
    // #endif
    ...options,
  })
}

/** Toast */
export function useToast(title: string, options?: Omit<UniApp.ShowToastOptions, 'title' | 'success' | 'fail' | 'complete'>) {
  return uni.showToast({
    title,
    duration: 800,
    icon: 'none',
    ...options,
  })
}

/** Loading */
export function useLoading(mask: boolean = true, options?: Omit<UniApp.ShowLoadingOptions, 'mask' | 'success' | 'fail' | 'complete'>) {
  return uni.showLoading({
    mask,
    ...options,
  })
}
export function useHideLoading() {
  // #ifdef MP-WEIXIN
  wx.hideLoading({
    fail: () => { },
  })
  // #endif

  // #ifndef MP-WEIXIN
  uni.hideLoading()
  // #endif
}

/** 页面滚动 */
export function usePageScrollTo(options: UniApp.PageScrollToOptions) {
  // 当前版本 uniapp 可能未配置支付宝小程序的 duration，所以得单独配置

  // #ifdef MP-ALIPAY
  my.pageScrollTo(options)
  // #endif

  // #ifndef MP-ALIPAY
  uni.pageScrollTo(options)
  // #endif
}

/** 页面安全区域 */
export function useSafeArea() {
  if (UNI_PLATFORM === 'h5') {
    const d = getComputedStyle(document.documentElement)
    return {
      top: Number.parseInt(d.getPropertyValue('--sat')),
      right: Number.parseInt(d.getPropertyValue('--sar')),
      bottom: Number.parseInt(d.getPropertyValue('--sab')),
      left: Number.parseInt(d.getPropertyValue('--sal')),
    }
  }
  else {
    return {
      top: 0,
      right: 0,
      bottom: 0,
      left: 0,
    }
  }
}

/** zod 校验 */
export function useZodParse() { }

/** zod ErrorMap */
export function useZodErrorMap(message: string) {
  return { errorMap: () => ({ message }) }
}

/** 路由参数守卫提示 */
export async function useRouteGuard() {
  await useModal({
    title: '无效访问',
    content: '即将返回首页',
    showCancel: false,
    confirmText: '返回',
  })
  useNavBack()
}

/** JSON 字符串深度解析 */
export function useJsonDeepParse<T = Record<string, any>>(obj: string): T {
  return JSON.parse(obj, (_key, value) => {
    if (typeof value === 'string' && (value.startsWith('{') || value.startsWith('['))) {
      try {
        return useJsonDeepParse(value)
      }
      catch {
        return value
      }
    }
    return value
  })
}

/** day.js 常规格式化 */
export function useDayjs(date?: dayjs.ConfigType) {
  const _date = (!isNil(date) || (typeof date && !isEmpty(date)))
    ? (/^\d+$/.test(`${date}`) ? Number.parseInt(`${date}`.padEnd(13, '0')) : date)
    : undefined
  return dayjs(_date)
}
export function useDayjsFormat(date: dayjs.ConfigType, limit: 'DD' | 'mm' | 'ss' = 'ss') {
  if (limit === 'DD') {
    return useDayjs(date).format('YYYY/MM/DD')
  }
  else if (limit === 'mm') {
    return useDayjs(date).format('YYYY/MM/DD HH:mm')
  }
  else {
    return useDayjs(date).format('YYYY/MM/DD HH:mm:ss')
  }
}

/** 定位 */
export async function useGetLocation() {
  useLoading(true)
  const [locationErr, locationRes] = await to(uni.getLocation())
  if (locationErr) {
    useHideLoading()
    const { confirm } = await useModal({
      title: '温馨提示',
      content: '请在设置中开启定位权限',
      confirmText: '去设置',
    })
    if (confirm) {
      return uni.openSetting()
    }
    return Promise.reject(locationErr)
  }

  const info = {
    ...pick(locationRes, ['latitude', 'longitude']),
    address: '',
  }

  const [err, res] = await to(orderApi.getAddressByJwd({
    location: [locationRes.latitude, locationRes.longitude].join(','),
  }))
  useHideLoading()
  if (err) {
    return info
  }

  const { province, city, district } = res.result.ad_info
  info.address = [province, city, district].join('-')
  return info
}

interface ChooseImageOptions {
  count: number
  sizeType?: ['original', 'compressed'] | ['original'] | ['compressed']
  sourceType?: ['album', 'camera'] | ['album'] | ['album']
  mediaType?: ['image', 'video'] | ['video'] | ['image']
}
/** 选择图片 */
export function useChooseImage(options: ChooseImageOptions) {
  const _options = Object.assign({}, {
    count: 1,
    sizeType: ['compressed'],
    sourceType: ['album', 'camera'],
  }, options)
  return new Promise<string[]>((resolve, reject) => {
    // #ifdef MP-WEIXIN
    uni.chooseMedia({
      ..._options,
      mediaType: ['image'],
      success: res => resolve(res.tempFiles.map(x => x.tempFilePath)),
      fail: err => reject(err),
    })
    // #endif
    // #ifndef MP-WEIXIN  ||  MP-KUAISHOU
    uni.chooseImage({
      ..._options,
      success: res => resolve(res.tempFilePaths as string[]),
      fail: err => reject(err),
    })
    // #endif
    // #ifdef MP-KUAISHOU
    ks.chooseMedia({
      ..._options,
      success: (res: any) => resolve([res.tempFiles[0].tempFilePath] as string[]),
      fail: (err: any) => reject(err),
    })
    // #endif
  })
}

interface ChooseVideoOptions {
  sourceType?: ['album', 'camera'] | ['album'] | ['album']
  camera?: 'front' | 'back'
  compressed?: boolean
  maxDuration?: number
}
/** 选择视频 */
export function useChooseVideo(options: ChooseVideoOptions) {
  const _options = Object.assign({}, {
    sourceType: ['album', 'camera'],
    camera: 'back',
  }, options)
  return new Promise<[string]>((resolve, reject) => {
    uni.chooseVideo({
      ..._options,
      success: (res) => {
        useConsole?.log(res)
        resolve([res.tempFilePath])
      },
      fail: err => reject(err),
    })
  })
}

/** 拨打客服 */
export function useCallCustomerService() {
  const phoneNumber = useAppConfig().appletSet.phone?.value
  if (isNil(phoneNumber) || isEmpty(phoneNumber)) {
    useToast('商户未配置联系方式')
    return
  }
  uni.makePhoneCall({ phoneNumber })
}
/** 手机号通用脱敏 */
export function usePhoneMasking(phone?: string | number | null) {
  if (isNil(phone)) {
    return ''
  }
  if (/^(?:\+86)?1\d{10}$/.test(phone.toString())) {
    return phone.toString().replace(/^(\+86)?(\d{3})\d{4}(\d{4})$/, '$2****$3')
  }
  return phone.toString().substring(0, 3)
}

/** 字符串脱敏 */
export function useStringMasking(content: string | null, front = 1, end = 1, mask = '****') {
  if (isNil(content)) {
    return ''
  }
  if (content.length < front + end) {
    return content
  }
  const regex = new RegExp(`(.{${front}})(?:.+)(.{${end}})`)
  return content.replace(regex, `$1${mask}$2`)
}
/** 快手端登录 跳转/清空登录 */
export function useKsUrlLogin(url: string | any) {
  // list-dict-item 字典 get-param-config 配置  app-product 商品
  const getList = ['list-dict-item', 'get-param-config', 'open/app-product']
  if (!url) {
    return
  }

  return getList.some(x => url.includes(x))
}

/** 信飞  铭鑫  鑫e  铨鑫  盛大 特别要求  后面要配置项  目前写死 */
export function useparticularly(url: string | any) {
  const getList = ['mingxin', 'quanxin', 'shengda', 'xinfei', 'xine']
  // 商品数量限制为1
  function getNumMax(): number {
    if (getList.includes(PRODUCT_ENV)) {
      return 1
    }
    return 99
  }
  // 租金计划隐藏
  function getRent(): boolean {
    if (getList.includes(PRODUCT_ENV)) {
      return false
    }
    return true
  }
  return {
    getNumMax,
    getRent,
  }
}
